package framework;

import java.util.Hashtable;

/**
 * This class implements a converter filter
 */
public class Converter extends FilterFramework {

	/**
	 * This variable represents the mappings between each measurement id 
	 * and the respective conversion function to be used.
	 */
	Hashtable<Integer, IConvertFunction> mappings;

	/**
	 * 
	 * Constructor
	 * 
	 * @param mappings the mappings between each measurement id 
	 * and the respective conversion function to be used.
	 */
	public Converter(Hashtable<Integer, IConvertFunction> mappings) {
		super(1, 1);
		this.mappings = mappings;
	}

	/**
	 * 
	 * This method reads the id of a measurement from the input pipe
	 * 
	 * @return The measurement id read
	 * @throws EndOfStreamException if the input pipe is closed or no more data in input pipe
	 */
	private int ReadInt() throws EndOfStreamException {
		return super.ReadInt(0);
	}

	/**
	 * 
	 * This method reads the value of a measurement from the input pipe
	 * 
	 * @return The measurement value read
	 * @throws EndOfStreamException if the input pipe is closed or no more data in input pipe
	 */
	private long ReadLong() throws EndOfStreamException {
		return super.ReadLong(0);
	}

	/**
	 * 
	 * This method writes the measurement id in the output pipe.
	 * 
	 * @param val the measurement id to write in the pipe
	 */
	protected void writeInt(int val) {
		this.writeInt(val, 0);
	}

	/**
	 * 
	 * This method writes the measurement value in the output pipe.
	 * 
	 * @param val the measurement value to write in the pipe
	 */
	protected void writeLong(long val) {
		this.writeLong(val, 0);
	}

	/**
	 * 
	 * This method connects one filter to the output port of this filter
	 * 
	 * @param Filter The filter that we want to connect to this filter
	 * @param OutputPortIndex The pipe port index where we want to connect the filter.
	 */
	public void Connect(FilterFramework Filter, int OutputPortIndex) {
		super.Connect(Filter, 0, OutputPortIndex);
	}

	/**
	 * The main method of the filter. Starts when the thread is launched
	 */
	@Override
	public void run() {
		while (true) {
			try {
				int id = this.ReadInt();
				long measure = this.ReadLong();
				IConvertFunction func = this.mappings.get(id);
				if (func != null) {
					measure = func.convert(measure);
				}

				this.writeInt(id);
				this.writeLong(measure);
			} catch (EndOfStreamException e) {
				ClosePorts();
				System.out.print("\n" + this.getName() + "::Converter Exiting;");
				break;
			} // catch
		}
	}
}
